package JET.physics;

import JET.geom.Vec2d;
import java.util.ArrayList;
import JET.Centers.ControlCenter;

/**
 *
 * @author 057Ry
 */
public class BodyFactory
{
    public static ArrayList<Object> buildSquareNet(ControlCenter CC, boolean doubleSprings, int dim, Vec2d v1, Vec2d v2, double m, double bf, double ff)
    {
        dim++;
        //System.out.println("buildSquareNet() dim ="+ dim);
        double cellWidth = (v2.getX() - v1.getX()) / (double)(dim-1);
        double cellHeight = (v2.getY() - v1.getY()) / (double)(dim-1);

        ArrayList<Mass> massList = new ArrayList<Mass>( (dim+1)*(dim+1) );
        for( int r=0; r<dim; r++)
            for( int c=0; c<dim; c++)
            {
//                double x = scene.GC.scrToEngineX( v1.getX() + cellWidth * r );
//                double y = scene.GC.scrToEngineY( v1.getY() + cellHeight * c );
                double x = v1.getX() + cellWidth * r;
                double y = v1.getY() + cellHeight * c;
                Mass mass = new Mass(x, y, m);
                massList.add( mass );
            }

        // tworzymy sprezyny
        int sNum = dim*(dim-1)*2 + (dim-1)*(dim-1)*2;
        ArrayList<Spring> springList = new ArrayList<Spring>( sNum );

        // sprezyny pionowe
        for( int r=0; r<dim-1; r++)
            for( int c=0; c<dim; c++)
            {
                int mIndex1 = r*dim + c;
                int mIndex2 = (r+1)*dim + c ;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }
        
        // sprezyny pionowe co 2 element
        if (doubleSprings)
        for( int r=0; r<dim-2; r++)
            for( int c=0; c<dim; c++)
            {
                int mIndex1 = r*dim + c;
                int mIndex2 = (r+2)*dim + c ;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }
        
        // sprezyny poziome
        for( int r=0; r<dim; r++)
            for( int c=0; c<dim-1; c++)
            {
                int mIndex1 = r*dim + c;
                int mIndex2 = r*dim + c +1;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }

        // sprezyny poziome co 2 element
        if (doubleSprings)
        for( int r=0; r<dim; r++)
            for( int c=0; c<dim-2; c++)
            {
                int mIndex1 = r*dim + c;
                int mIndex2 = r*dim + c +2;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }
        
        // sprezyny skosne 1 (lewa gora - prawy dol)
        for( int r=0; r<dim-1; r++)
            for( int c=0; c<dim-1; c++)
            {
                int mIndex1 = r*dim + c;
                int mIndex2 = (r+1)*dim + c +1;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }

        // sprezyny skosne 1 (lewa gora - prawy dol) co 2 element
        if (doubleSprings)
        for( int r=0; r<dim-2; r++)
            for( int c=0; c<dim-2; c++)
            {
                int mIndex1 = r*dim + c;
                int mIndex2 = (r+2)*dim + c+2;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }
        
        // sprezyny skosne 2 (prawy gorny - lewy dolny)
        for( int r=0; r<dim-1; r++)
            for( int c=0; c<dim-1; c++)
            {
                int mIndex1 = r*dim + c+1;
                int mIndex2 = (r+1)*dim + c;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }

        // sprezyny skosne 2 (prawy gorny - lewy dolny) co 2 element
        if (doubleSprings)
        for( int r=0; r<dim-2; r++)
            for( int c=0; c<dim-2; c++)
            {
                int mIndex1 = r*dim + c+2;
                int mIndex2 = (r+2)*dim + c;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Spring spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springList.add( spring );
            }

        ArrayList<Wall> wallList = new ArrayList<Wall>( (dim+1)*4 );
        
        // sciany pionowe
        for (int c=0; c<dim; c+=dim-1)
            for (int r=0; r<dim-1; r++)
            {
                int mIndex1 = r*dim + c;
                int mIndex2 = (r+1)*dim + c;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Wall wall = new Wall(mass1, mass2);
                wallList.add( wall );

            }
        
        // sciany poziome
        for( int r=0; r<dim; r+=dim-1)
            for( int c=0; c<dim-1; c++)
            {
                int mIndex1 = c + r*dim;
                int mIndex2 = c+1 + r*dim;
                Mass mass1 = massList.get(mIndex1);
                Mass mass2 = massList.get(mIndex2);

                Wall wall = new Wall(mass1, mass2);
                wallList.add( wall );
            }


        ArrayList<Object> resultList = new ArrayList<Object>(1);
        resultList.add( massList );
        resultList.add( wallList );
        resultList.add( springList );

        return resultList;

    }
    public static ArrayList<Object> bulidCircle(ControlCenter CC, Vec2d v1, Vec2d v2, int pNum, double m, double bf, double ff)
    {
        // zapewneinie odpowiednij liczby punktow
        if ( pNum<3 ) pNum = 3;
        Vec2d vec = new Vec2d( v2 );
        vec.sub( v1 );

        double dAngle = Math.PI*2 / pNum;
        ArrayList<Mass> masses = new ArrayList<Mass>( pNum );

        for( int i=0; i<pNum; i++ )
        {
            Vec2d pos = vec.getRotated(-dAngle * i);
            Mass mass = new Mass(pos.getX() + v1.getX(),
                                     pos.getY() + v1.getY(),
                                     m);
            masses.add( mass );
        }

        // tworzymy sciany okregu
        ArrayList<Wall> walls = new ArrayList<Wall>();
        if ( CC.MC.createCircleWalls )
        {
            for( int i=0; i<masses.size()-1; i++)
            {
                Mass mass1 = masses.get(i);
                Mass mass2 = masses.get(i+1);
                Wall wall = new Wall(mass1, mass2);
                walls.add( wall );
            }
            Mass mass1 = masses.get( masses.size()-1);
            Mass mass2 = masses.get( 0 );
            Wall wall = new Wall(mass1, mass2);
            walls.add( wall );
        }

        // tworzymy sprezyny okregu
        ArrayList<Spring> springs = new ArrayList<Spring>();

        // sprezyny na obwodzie
        Mass mass1, mass2;
        Spring spring;
        for( int i=0; i<masses.size()-1; i++)
        {
            mass1 = masses.get(i);
            mass2 = masses.get(i+1);
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }
        mass1 = masses.get(masses.size()-1);
        mass2 = masses.get(0);
        spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
        springs.add(spring);

        // sprezyny wew okregu - na srednicy
        int n;
        if ( pNum%2 == 0 ) n = masses.size()/2;
        else n = masses.size()/2 + 1;

        for( int i=0; i<n; i++)
        {
            mass1 = masses.get(i);
            mass2 = masses.get( i+ pNum/2 );
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }

        ArrayList<Object> resultList = new ArrayList<Object>();
        resultList.add( masses );
        resultList.add( walls );
        resultList.add( springs );

        return resultList;
    }
    public static ArrayList<Object> bulidCenterPointCircle(ControlCenter CC, Vec2d v1, Vec2d v2, int pNum, double m, double bf, double ff)
    {
        // zapewneinie odpowiednij liczby punktow
        if ( pNum<3 ) pNum = 3;
        Vec2d vec = new Vec2d( v2 );
        vec.sub( v1 );
        
        double dAngle = Math.PI*2 / pNum;
        ArrayList<Mass> masses = new ArrayList<Mass>( pNum );

        for( int i=0; i<pNum; i++ )
        {
            Vec2d pos = vec.getRotated(-dAngle * i);
            Mass mass = new Mass(pos.getX() + v1.getX(),
                                     pos.getY() + v1.getY(),
                                     m);
            masses.add( mass );
        }
        
        // tworzymy sciany okregu
        ArrayList<Wall> walls = new ArrayList<Wall>();
        if ( CC.MC.createCircleWalls )
        {
            for( int i=0; i<masses.size()-1; i++)
            {
                Mass mass1 = masses.get(i);
                Mass mass2 = masses.get(i+1);
                Wall wall = new Wall(mass1, mass2);
                walls.add( wall );
            }
            Mass mass1 = masses.get( masses.size()-1);
            Mass mass2 = masses.get( 0 );
            Wall wall = new Wall(mass1, mass2);
            walls.add( wall );
        }

        // dodajemy srodkowa mase
        Mass mass = new Mass(v1.getX(),
                                 v1.getY(),
                                 m);
        masses.add( mass );

        // tworzymy sprezyny okregu
        ArrayList<Spring> springs = new ArrayList<Spring>();
            
        // sprezyny na obwodzie
        Mass mass1, mass2;
        Spring spring;
        for( int i=0; i<masses.size()-2; i++)
        {
            mass1 = masses.get(i);
            mass2 = masses.get(i+1);
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }
        mass1 = masses.get(masses.size()-2);
        mass2 = masses.get(0);
        spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
        springs.add(spring);

        // sprezyny wew okregu
        for( int i=0; i<masses.size()-1; i++)
        {
            mass1 = masses.get(i);
            mass2 = masses.get( masses.size()-1 );
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }
        
        ArrayList<Object> resultList = new ArrayList<Object>();
        resultList.add( masses );
        resultList.add( walls );
        resultList.add( springs );
        return resultList;
    }
    public static ArrayList<Object> bulidCenterPointCircleWithDoubleSprings(ControlCenter CC, Vec2d v1, Vec2d v2, int pNum, double m, double bf, double ff)
    {
        // zapewniamy parzystosc punktow
        if ( pNum%2 != 0 ) pNum++;
        
        Vec2d vec = new Vec2d( v2 );
        vec.sub( v1 );
        
        double dAngle = Math.PI*2 / pNum;
        ArrayList<Mass> masses = new ArrayList<Mass>( pNum );

        for( int i=0; i<pNum; i++ )
        {
            Vec2d pos = vec.getRotated(-dAngle * i);
//            Mass mass = new Mass(scene.GC.scrToEngineX( pos.getX() + v1.getX() ),
//                                     scene.GC.scrToEngineY( pos.getY() + v1.getY() ),
//                                     m, bf, ff );
            Mass mass = new Mass(pos.getX() + v1.getX(),
                                     pos.getY() + v1.getY(),
                                     m);
            masses.add( mass );
        }
        
        // tworzymy sciany okregu
        ArrayList<Wall> walls = new ArrayList<Wall>();
        if ( CC.MC.createCircleWalls )
        {
            for( int i=0; i<masses.size()-1; i++)
            {
                Mass mass1 = masses.get(i);
                Mass mass2 = masses.get(i+1);
                Wall wall = new Wall(mass1, mass2);
                walls.add( wall );
            }
            Mass mass1 = masses.get( masses.size()-1);
            Mass mass2 = masses.get( 0 );
            Wall wall = new Wall(mass1, mass2);
            walls.add( wall );
        }

        // dodajemy srodkowa mase
//        Mass mass = new Mass(scene.GC.scrToEngineX( v1.getX() ),
//                                 scene.GC.scrToEngineY( v1.getY() ),
//                                 m, bf, ff );
        Mass mass = new Mass(v1.getX(),
                                 v1.getY(),
                                 m);
        masses.add( mass );

        // tworzymy sprezyny okregu
        ArrayList<Spring> springs = new ArrayList<Spring>();
            
        // sprezyny na obwodzie
        Mass mass1, mass2;
        Spring spring;
        for( int i=0; i<masses.size()-2; i++)
        {
            mass1 = masses.get(i);
            mass2 = masses.get(i+1);
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }
        mass1 = masses.get(masses.size()-2);
        mass2 = masses.get(0);
        spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
        springs.add(spring);

        // dodatkowe sprezyny na obwodzie , co 1 mase
        if ( pNum > 4)
        {
            // laczace masy parzyste
            for( int i=0; i<masses.size()-4; i+=2)
            {
                mass1 = masses.get( i );
                mass2 = masses.get( i+2 );
                spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springs.add(spring);
            }
            mass1 = masses.get( masses.size()-3 );
            mass2 = masses.get( 0 );
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
            // laczace masy nieparzyste
            for( int i=1; i<masses.size()-3; i+=2)
            {
                mass1 = masses.get( i );
                mass2 = masses.get( i+2 );
                spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
                springs.add(spring);
            }
            mass1 = masses.get( masses.size()-2 );
            mass2 = masses.get( 1 );
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }
        
        //sprezyny wew okregu - na promieniu
        for( int i=0; i<masses.size()-1; i++)
        {
            mass1 = masses.get(i);
            mass2 = masses.get( masses.size()-1 );
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }
        
        // sprezyny wew okregu - na srednicy
        for( int i=0; i<masses.size()/2; i++)
        {
            mass1 = masses.get(i);
            mass2 = masses.get( i+ pNum/2 );
            spring = new Spring(mass1, mass2, Spring.Type.SpringBody);
            springs.add(spring);
        }
        
        ArrayList<Object> resultList = new ArrayList<Object>();
        resultList.add( masses );
        resultList.add( walls );
        resultList.add( springs );
        return resultList;
    }

}
